home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
- #include <stdlib.h>
- #include <math.h>
- #include <egb.h>
- #include <nslib.h>
- #include "pc_inc.h"
-
- #define BUFFER (16384)
-
-
- static void equation( int *d, int h, int *u )
- {
- int i, j, k;
- int tmp,
- m[3][4] = { { 65536, 16384, 0, 0 },
- { 16384, 65536, 16384, 0 },
- { 0, 16384, 65536, 0 } };
-
- /* 行列の作成 */
- tmp = MUL( h, h );
- for( i=0; i<3; i++ )
- m[i][3] = DIV( ( d[i+2] - d[i+1]*2 + d[i] )*3, 2*tmp );
-
- /* 方程式を解く */
- for( i=0; i<3; i++ ) /* 引く行 */
- for( j=0; j<3; j++ ) /* 引かれる行 */
- if ( i != j )
- for( k=0; k<4; k++ ) /* 列 */
- m[j][k] -= MUL( m[i][k], m[j][i] );
- for( i=0; i<3; i++ )
- u[i+1] = m[i][3];
- }
-
- static void equation2( int *d, int h, int *u )
- {
- int tmp=MUL(h,h);
-
- u[2] = u[3];
-
- /* 方程式を解く */
- u[3] = ( DIV( (d[2]-d[3]*2+d[4])*6, tmp ) -u[2] )/4;
- }
-
- static void rate( schar *pcm, schar *buf, int is, int os )
- {
- int i, idx=0, d[]={0,0,0,0,0}, u[]={0,0,0,0,0}, h, re, t1, t2,
- si=0, di=0;
-
- h = FIX(os) / is;
-
- _fill_d( d, FIX((int)pcm[0]), 2 );
- for( i=2; i<5; i++ )
- d[i] = FIX((int)pcm[idx++]);
-
- equation( d, h, u );
-
- for( i=0; i<is; i++ )
- {
- while( si < h )
- {
- t1 = si-h;
- t2 = MUL( h, h );
- re = DIV(
- - MUL( MUL(u[2],t1), MUL(t1,t1) )
- + MUL( MUL(u[3],si), MUL(si,si) )
- + MUL( ( 6*d[3] - MUL(u[3], t2) ), si )
- - MUL( ( 6*d[2] - MUL(u[2], t2) ), t1 )
- , (6*h) );
-
- if ( re < 0 )
- {
- re = -INT(-re);
- if ( re < -127 )
- re = -127;
- }
- else
- {
- re = INT(re);
- if ( re > 126 )
- re = 126;
- }
- buf[di++] = (schar)re;
- si += FIX(1);
- }
- si -= h;
-
- _copy_d( d, d+1, 4 );
- if ( idx < is )
- d[4] = FIX( (int)pcm[idx++] );
- else
- d[4] = FIX( (int)pcm[is-1] );
- equation2( d, h, u );
- }
- }
-
- void ctosc( schar *src, int n )
- {
- int i;
-
- for( i=0; i<n; i++ )
- if ( src[i] & 0x80 )
- src[i] &= 127;
- else
- src[i] = -src[i];
- }
-
- void sctoc( schar *src, int n )
- {
- int i;
-
- for( i=0; i<n; i++ )
- if ( src[i] & 0x80 )
- src[i] = (src[i]^255)+1;
- else
- src[i] |= 128;
- }
-
- static void predict( schar *pcm, int n )
- {
- int i, a, a0=0, a1=0, tmp;
-
- for( i=2; i<n; i++ )
- {
- a = 2*( (int)pcm[i-1]+a1 ) - ( (int)pcm[i-2]+a0 );
- if ( a > 127 )
- a = 127;
- else if ( a < -127 )
- a = -127;
- a0 = a1; a1 = a;
- tmp = (int)pcm[i] - a;
- if ( tmp < -128 )
- tmp = -128;
- else if ( tmp > 127 )
- tmp = 127;
- pcm[i] = (schar)tmp;
- }
- }
-
- static void predict_decode( schar *pcm, int n )
- {
- int i, a, tmp;
-
- for( i=2; i<n; i++ )
- {
- a = 2*(int)pcm[i-1] - (int)pcm[i-2];
- if ( a > 127 )
- a = 127;
- else if ( a < -127 )
- a = -127;
- tmp = (int)pcm[i] + a;
- pcm[i] = BYTE( &tmp );
- }
- }
-
- static void dpcm( schar *pcm, int n )
- {
- int i, e=0, val;
-
- val = pcm[0];
- for( i=1; i<BUFFER; i++ )
- {
- e = (int)(pcm[i]-val);
- if ( e < -128 )
- e = -128;
- else if ( e > 127 )
- e = 127;
- pcm[i] = (schar)e;
- val += e;
- }
- }
-
- static void dpcm_decode( schar *pcm, int n )
- {
- int i;
-
- for( i=1; i<BUFFER; i++ )
- pcm[i] += pcm[i-1];
- }
-
- static int fft_comp( schar *pcm )
- {
- int i, max, si, di=BUFFER/N;
- short *rl, *im;
- schar *buf;
-
- rl = malloc( N*4 );
- if ( rl == NULL ) return (-1);
- im = rl+N;
- buf = malloc( BUFFER );
- if ( buf == NULL )
- {
- free( rl );
- return (-1);
- }
-
- for( si=0; si<BUFFER; si+=N )
- {
- /* FFT */
- for( i=0; i<N; i++ )
- rl[i] = (short)pcm[si+i];
- _fill_w( im, 0, N );
- time_window( rl );
- fft( rl, im, 0 );
- for( i=N/2-1; rl[i]*rl[i]+im[i]*im[i] <= 9 && i>1; i-- );
- buf[si/N] = (schar)i;
- max = (i+1)*2;
- if ( di+max > BUFFER )
- { free( rl ); free ( buf ); return (-2); }
- rate( pcm+si, buf+di, N, max );
- di += max;
- }
- _copy_b( pcm, buf, di );
-
- free( rl );
- free( buf );
- return ( di );
- }
-
- static int fft_exp( schar *pcm, schar next )
- {
- int src, di, si=BUFFER/N;
- schar *buf;
-
- buf = malloc( BUFFER );
- if ( buf == NULL ) return (-1);
-
- for( di=0; di<BUFFER; di+=N )
- {
- src = ((int)pcm[di/N]+1)*2;
- rate( pcm+si, buf+di, src, N );
- si += src;
- }
- for( di=N; di<BUFFER; di+=N )
- buf[di-1] = (schar)( ((int)buf[di-2]+(int)buf[di])/2 );
- buf[BUFFER-1] = (schar)( ((int)buf[BUFFER-2]+(int)next)/2 );
-
- _copy_b( pcm, buf, BUFFER );
-
- free( buf );
- return ( BUFFER );
- }
-
- int compress( char *inputfile, char *outputfile, char *n )
- {
- FILE *fp_i;
- BIT_FILE *fp_o;
- schar *pcmbuf;
- char header[32], proc[][4] = { "1A", "2A", "1B", "2B", "31A", "32A" },
- *msg1 = "入力ファイル: bytes",
- *msg2 = "出力ファイル: bytes",
- *msg3 = "圧縮率 : . %";
- int size, ds, rb, bits=40*8, pn, i, ret=0;
-
- pn = (int)n[0]-49;
- if ( pn < 0 || 5 < pn )
- { ret = 10; goto end4; }
-
- if ( ( pcmbuf = malloc( BUFFER ) ) == NULL )
- { ret = 6; goto end4; }
-
- if ( ( fp_i = fopen( inputfile, "rb" ) ) == NULL )
- { ret = 1; goto end3; }
- if ( ( fp_o = BIT_open( outputfile, "wb" ) ) == NULL )
- { ret = 2; goto end2; }
-
- if ( BIT_write_bytes( "PC\x01\x10", 4, 1, fp_o ) < 1 )
- { ret = 4; goto end1; }
- if ( BIT_write_bytes( proc[pn], 4, 1, fp_o ) < 1 )
- { ret = 4; goto end1; }
- if ( fread( header, 32, 1, fp_i ) < 1 )
- { ret = 3; goto end1; }
- if ( BIT_write_bytes( header, 32, 1, fp_o ) < 1 )
- { ret = 4; goto end1; }
-
- size = DWORD( header+12 );
-
- /* FFTの準備 */
- sin_cos();
- bitrev();
-
- do {
- /* データ読み込み */
- if ( ( rb = fread( pcmbuf, 1, BUFFER, fp_i ) ) < BUFFER )
- _fill_b( pcmbuf+rb, 0x80, BUFFER-rb );
- ds = BUFFER;
- ctosc( pcmbuf, BUFFER ); /* PCM データを2の補数に変換 */
-
- /* encode */
- for( i=0; proc[pn][i]; i++ )
- switch( proc[pn][i] )
- {
- case '1':
- predict( pcmbuf, ds );
- break;
- case '2':
- dpcm( pcmbuf, ds );
- break;
- case '3':
- if ( ( ds = fft_comp( pcmbuf ) ) == -1 )
- {
- if ( ds == -1 ) ret = 13;
- else if ( ds == -2 ) ret = 14;
- goto end1;
- }
- break;
- case 'A':
- if ( ( ds = huff_comp( (char *)pcmbuf, ds, fp_o ) ) == -1 )
- { ret = 12; goto end1; }
- bits += ds*8;
- break;
- case 'B':
- if ( ( ds = lzw_comp( (char *)pcmbuf, ds, fp_o ) ) < 0 )
- { ret = 11; goto end1; }
- bits += ds;
- }
- size -= BUFFER;
- }
- while( size > 0 );
-
- bits = (bits+7)/8;
- size = DWORD( header+12 )+32;
- _to_dec( &msg1[13], size, 10 );
- _to_dec( &msg2[13], bits, 10 );
- if ( size > 100000000 )
- _to_dec( &msg3[20], size/bits, 3 );
- else
- {
- _to_dec( &msg3[17], bits*100/size, 3 );
- _to_dec( &msg3[21], bits*10000/size, 2 );
- }
- puts( msg1 );
- puts( msg2 );
- puts( msg3 );
-
- end1:BIT_close( fp_o );
- end2:fclose( fp_i );
- end3:free( pcmbuf );
- end4:return ( ret );
- }
-
- int expand( char *inputfile, char *outputfile )
- {
- BIT_FILE *fp_i;
- FILE *fp_o;
- int i, size, tmp, sw, ds, ret=0;
- char header[32], proc[4];
- schar *pcmbuf[2];
-
- if ( ( pcmbuf[0] = malloc( BUFFER*2 ) ) == NULL )
- { ret = 6; goto end4; }
- pcmbuf[1] = pcmbuf[0]+BUFFER;
-
- if ( ( fp_o = fopen( outputfile, "wb" ) ) == NULL )
- { ret = 2; goto end3; }
- if ( ( fp_i = BIT_open( inputfile, "rb" ) ) == NULL )
- { ret = 1; goto end2; }
-
- if ( BIT_read_bytes( &tmp, 4, 1, fp_i ) < 1 )
- { ret = 3; goto end1; }
- if ( BIT_read_bytes( proc, 4, 1, fp_i ) < 1 )
- { ret = 3; goto end1; }
- if ( BIT_read_bytes( header, 32, 1, fp_i ) < 1 )
- { ret = 3; goto end1; }
- if ( fwrite( header, 32, 1, fp_o ) < 1 )
- { ret = 4; goto end1; }
-
- size = DWORD( header+12 );
-
- _fill_b( pcmbuf[0], 0x80, BUFFER*2 );
- for( i=_len(proc)-1; proc[i]!='3' && (i>=0); i-- )
- switch( proc[i] )
- {
- case 'A':
- ds = huff_exp( (char *)pcmbuf[0], fp_i );
- break;
- case 'B':
- ds = lzw_exp( (char *)pcmbuf[0], fp_i );
- break;
- case '1':
- predict_decode( pcmbuf[0], ds );
- break;
- case '2':
- dpcm_decode( pcmbuf[0], ds );
- }
- sw = 1;
-
- do {
- /* read */
- _fill_b( pcmbuf[sw], 0, BUFFER );
- for( i=_len(proc)-1; proc[i]!='3' && (i>=0); i-- )
- switch( proc[i] )
- {
- case 'A':
- ds = huff_exp( (char *)pcmbuf[sw], fp_i );
- break;
- case 'B':
- ds = lzw_exp( (char *)pcmbuf[sw], fp_i );
- break;
- case '1':
- predict_decode( pcmbuf[sw], ds );
- break;
- case '2':
- dpcm_decode( pcmbuf[sw], ds );
- }
- sw ^= 1;
-
- /* decode */
- if ( proc[i] == '3' )
- if ( fft_exp( pcmbuf[sw], pcmbuf[1-sw][BUFFER/N] ) == -1 )
- { ret = 13; goto end1; }
-
- /* ファイルへ出力 */
- sctoc( pcmbuf[sw], BUFFER );
- if ( size < BUFFER )
- {
- if ( fwrite( pcmbuf[sw], size, 1, fp_o ) < 1 )
- { ret = 5; goto end1; }
- }
- else
- if ( fwrite( pcmbuf[sw], BUFFER, 1, fp_o ) < 1 )
- { ret = 5; goto end1; }
- size -= BUFFER;
- }
- while( size > 0 );
-
- end1:BIT_close( fp_i );
- end2:fclose( fp_o );
- end3:free( pcmbuf[0] );
- end4:return ( ret );
- }
-